﻿using System;
using System.Collections.Generic;
using ObjectPool;

namespace Entity
{
    public sealed partial class EntityManager
    {
        private sealed class EntityGroup : IEntityGroup
        {
            /// <summary>
            /// 实体组名称
            /// </summary>
            private readonly string m_Name;
            /// <summary>
            /// 实体组辅助器
            /// </summary>
            private readonly IEntityGroupHelper m_EntityGroupHelper;
            /// <summary>
            /// 实体组实例对象池
            /// </summary>
            private readonly IObjectPool<EntityInstanceObject> m_InstancePool;
            /// <summary>
            /// 
            /// </summary>
            private readonly List<IEntity> m_Entities;
            private List<IEntity> m_CachedNode;
            
            
            /// <summary>
            /// 初始化实体组的新实例
            /// </summary>
            /// <param name="name">实体组名称</param>
            /// <param name="instanceAutoReleaseInterval">实体实例对象池自动释放可释放对象的间隔秒数</param>
            /// <param name="instanceCapacity">实体实例对象池容量</param>
            /// <param name="instanceExpireTime">实体实例对象池对象过期秒数</param>
            /// <param name="instancePriority">实体实例对象池的优先级</param>
            /// <param name="entityGroupHelper">对象池辅助器</param>
            /// <param name="objectPoolManager">对象池管理器</param>
            public EntityGroup(string name, float instanceAutoReleaseInterval, int instanceCapacity, float instanceExpireTime,
            int instancePriority, IEntityGroupHelper entityGroupHelper, IObjectPoolManager objectPoolManager)
            {
                if (string.IsNullOrEmpty(name))
                    throw new Exception("Entity group name is invalid.");
                if (entityGroupHelper == null)
                    throw new Exception("Entity group helper is invalid.");

                m_Name = name;
                m_EntityGroupHelper = entityGroupHelper;
                m_InstancePool = objectPoolManager.CreateSingleSpawnObjectPool<EntityInstanceObject>(string.Format("Entity Instance Pool ({0})", name), instanceCapacity, instanceExpireTime, instancePriority);
                m_InstancePool.AutoReleaseInterval = instanceAutoReleaseInterval;
                m_Entities = new List<IEntity>();
                m_CachedNode = null;
            }

            /// <summary>
            /// 获取实体组名称
            /// </summary>
            public string Name
            {
                get
                {
                    return m_Name;
                }
            }
            
            /// <summary>
            /// 获取实体组中实体数量
            /// </summary>
            public int EntityCount
            {
                get
                {
                    return m_Entities.Count;
                }
            }

            /// <summary>
            /// 获取或设置实体组实例对象池自动释放可释放对象的间隔秒数
            /// </summary>
            public float InstanceAutoReleaseInterval
            {
                get
                {
                    return m_InstancePool.AutoReleaseInterval;
                }
                set
                {
                    m_InstancePool.AutoReleaseInterval = value;
                }
            }

            /// <summary>
            /// 获取实体组实例对象池容量
            /// </summary>
            public int InstanceCapacity
            {
                get
                {
                    return m_InstancePool.Capacity;
                }
                set
                {
                    m_InstancePool.Capacity = value;
                }
            }

            /// <summary>
            /// 获取或设置实体组实例对象池对象过期秒数
            /// </summary>
            public float InstanceExpireTime
            {
                get
                {
                    return m_InstancePool.ExpireTime;
                }
                set
                {
                    m_InstancePool.ExpireTime = value;
                }
            }
            
            /// <summary>
            /// 获取或设置实体组实例对象池的优先级。
            /// </summary>
            public int InstancePriority
            {
                get
                {
                    return m_InstancePool.Priority;
                }
                set
                {
                    m_InstancePool.Priority = value;
                }
            }

            /// <summary>
            /// 获取实体组辅助器。
            /// </summary>
            public IEntityGroupHelper Helper
            {
                get
                {
                    return m_EntityGroupHelper;
                }
            }
            
            /// <summary>
            /// 实体组轮询，这么写在多线程中会出错
            /// </summary>
            /// <param name="elapseSeconds"></param>
            /// <param name="realElapseSeconds"></param>
            public void Update(float elapseSeconds, float realElapseSeconds)
            {
                foreach (var mEntity in m_Entities)
                {
                    mEntity.OnUpdate(elapseSeconds, realElapseSeconds);
                }
            }

            /// <summary>
            /// 实体组中是否存在实体
            /// </summary>
            /// <param name="entityId"></param>
            /// <returns></returns>
            public bool HasEntity(int entityId)
            {
                foreach (IEntity entity in m_Entities)
                {
                    if(entity.Id == entityId)
                        return true;
                }
                return false;
            }

            /// <summary>
            /// 实体组中是否存在实体
            /// </summary>
            /// <param name="entityAssetName"></param>
            /// <returns></returns>
            /// <exception cref="Exception"></exception>
            public bool HasEntity(string entityAssetName)
            {
                if (string.IsNullOrEmpty(entityAssetName))
                    throw new Exception("Entity asset name is invalid.");

                foreach (IEntity entity in m_Entities)
                {
                    if (entity.EntityAssetName == entityAssetName)
                        return true;
                }
                return false;
            }
            
            /// <summary>
            /// 获取实体组中的实体
            /// </summary>
            /// <param name="entityId"></param>
            /// <returns></returns>
            public IEntity GetEntity(int entityId)
            {
                foreach (IEntity entity in m_Entities)
                {
                    if (entity.Id == entityId)
                        return entity;
                }
                return null;
            }
            
            /// <summary>
            /// 获取实体组中的实体
            /// </summary>
            /// <param name="entityAssetName"></param>
            /// <returns></returns>
            public IEntity GetEntity(string entityAssetName)
            {
                if (string.IsNullOrEmpty(entityAssetName))
                    throw new Exception("Entity asset name is invalid.");

                foreach (IEntity entity in m_Entities)
                {
                    if (entity.EntityAssetName == entityAssetName)
                        return entity;
                }
                return null;
            }
            
            /// <summary>
            /// 获取实体组中的实体
            /// </summary>
            /// <param name="entityAssetName"></param>
            /// <returns></returns>
            public IEntity[] GetEntities(string entityAssetName)
            { 
                if (string.IsNullOrEmpty(entityAssetName))
                    throw new Exception("Entity asset name is invalid.");
                List<IEntity> results = new List<IEntity>();
                foreach (IEntity entity in m_Entities)
                {
                    if (entity.EntityAssetName == entityAssetName)
                        results.Add(entity);
                }
                return results.ToArray();
            }

            /// <summary>
            /// 从实体组中获取实体
            /// </summary>
            /// <param name="entityAssetName">实体资源名称</param>
            /// <param name="results">要获取的实体</param>
            public void GetEntities(string entityAssetName, List<IEntity> results)
            {
                if(string.IsNullOrEmpty(entityAssetName))
                    throw new Exception("Entity asset name is invalid.");
                if(results == null)
                    throw new Exception("Results is invalid.");
                results.Clear();
                foreach (var mEntity in m_Entities)
                {
                    if(mEntity.EntityAssetName == entityAssetName)
                        results.Add(mEntity);
                }    
            }
            
            /// <summary>
            /// 获取实体组中的所有实体
            /// </summary>
            /// <returns></returns>
            public IEntity[] GetAllEntities()
            {
                return m_Entities.ToArray();
            }
            
            /// <summary>
            /// 获取实体组中的所有实体
            /// </summary>
            /// <param name="results"></param>
            /// <exception cref="Exception"></exception>
            public void GetAllEntities(List<IEntity> results)
            {
                if(results == null)
                    throw new Exception("Results is invalid.");
                results.Clear();
                results.AddRange(m_Entities);
            }

            /// <summary>
            /// 往实体组增加实体
            /// </summary>
            /// <param name="entity"></param>
            public void AddEntity(IEntity entity)
            {
                m_Entities.Add(entity);
            }
            
            /// <summary>
            /// 移除实体组中的实体
            /// </summary>
            /// <param name="entity"></param>
            /// <exception cref="Exception"></exception>
            public void RemoveEntity(IEntity entity)
            {
                if(!m_Entities.Remove(entity))
                    throw new Exception(string.Format("Entity group '{0}' not exists specified entity '[{1}]{2}'.", m_Name, entity.Id, entity.EntityAssetName));
            }

            public void RegisterEntityInstanceObject(EntityInstanceObject obj, bool spawned)
            {
                m_InstancePool.Register(obj, spawned);
            }
            
            public EntityInstanceObject SpawnEntityInstanceObject(string name)
            {
                return m_InstancePool.Spawn(name);
            }
            
            
            public void UnspawnEntity(IEntity entity)
            {
                m_InstancePool.Unspawn(entity);
            }

            /// <summary>
            /// 设置实体实例的锁定状态
            /// </summary>
            /// <param name="entityInstance"></param>
            /// <param name="locked"></param>
            public void SetEntityInstanceLocked(object entityInstance, bool locked)
            {
                if(entityInstance == null)
                    throw new Exception("Entity instance is invalid.");
                m_InstancePool.SetLocked(entityInstance, locked);
            }
            
            /// <summary>
            /// 设置实体实例的优先级
            /// </summary>
            /// <param name="entityInstance"></param>
            /// <param name="priority"></param>
            /// <exception cref="Exception"></exception>
            public void SetEntityInstancePriority(object entityInstance, int priority)
            {
                if(entityInstance == null)
                    throw new Exception("Entity instance is invalid.");
                m_InstancePool.SetPriority(entityInstance, priority);
            }

        }
        
    }
}